package com.cloudbroker.bcs.platform.dav.middle.bizservice.impl;

import com.cloudbroker.bcs.common.entity.HSBCPSBackNumVO;
import com.cloudbroker.bcs.common.util.DateUtil;
import com.cloudbroker.bcs.common.util.StringUtil;
import com.cloudbroker.bcs.common.util.VOUtil;
import com.cloudbroker.bcs.common.util.ValueUtil;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.HSBCPSErrorCodes;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.HSBCPSErrorCodes.QuestionErr;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.HSBCPSErrorCodes.SysMgtErr;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.status.AnswerStatus;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.status.UpvoteStatus;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.type.ViewpointStatusType;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.type.VoteType;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.customer.vo.BatchImportVoteForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.customer.vo.BatchImportVoteListForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.customer.vo.BatchImportZXConfigForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.customer.vo.BatchImportZXConfigListForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.UpvoteBizService;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.back.BatchImportVoteBackForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.back.VoteRecordListBack;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.back.VoteRecordListData;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.vo.BrokerUpvoteClickForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.vo.ClickUpvoteForm;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.upvote.vo.RecordListForm;
import com.cloudbroker.bcs.platform.dav.common.config.ConfigValues;
import com.cloudbroker.bcs.platform.dav.common.constant.CacheKeys;
import com.cloudbroker.bcs.platform.dav.common.util.CacheHelper;
import com.cloudbroker.bcs.platform.dav.middle.context.HSBCPSBizDataContext;
import com.cloudbroker.bcs.platform.dav.middle.entity.*;
import com.cloudbroker.bcs.platform.dav.middle.entityexample.BrokerFinanceQueryCondition;
import com.cloudbroker.bcs.platform.dav.middle.entityexample.BrokerVoteQueryCondition;
import com.cloudbroker.bcs.platform.dav.middle.entityview.VoteRecordListView;
import com.cloudbroker.bcs.platform.dav.middle.extservice.point.PointAddService;
import com.cloudbroker.bcs.platform.dav.middle.service.*;
import com.cloudbroker.bcs.platform.dav.middle.util.PositionStrUtil;
import com.cloudbroker.bcs.platform.dav.middle.util.point.PointType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class UpvoteBizServiceImpl implements UpvoteBizService {
    private static final Logger logger = LoggerFactory.getLogger(UpvoteBizServiceImpl.class);
    @Resource
    private ViewpointMsgService viewpointMsgService;
    
    @Resource
    private UpvoteWaterService upvoteWaterService;
    
    @Resource
    private QuestionService questionSerivce;
    
    @Resource
    private BrokerVoteLogService brokerVoteLogService;
    @Resource
    private BrokerVoteService brokerVoteService;
    @Resource
    private ZXBrokerFinanceService zxBrokerFinanceService;
    
    @Resource
    private BrokerService brokerService;
    @Resource
    private BrokerManagerService brokerManagerService;
    
    @Resource
    private TenantService tenantService;
    
    @Resource
    private PointAddService pointAddService;
    
    private volatile Date lastManageZXConfigDate = null;
    private static Map<Integer, List<BrokerFinance>> brokerFinancesMap = new HashMap<>();
    
    @Override
    public HSBCPSBackNumVO funcClickUpvote(ClickUpvoteForm param) {
        
        HSBCPSBackNumVO vo = new HSBCPSBackNumVO();
        
        String target_id = param.getTarget_id();
        String target_type = param.getTarget_type();
        String broker_id_bak = param.getBroker_id();
        Long broker_id = HSBCPSBizDataContext.getBrokerId();
        Customer customer = HSBCPSBizDataContext.getCustomer();
        if (null == broker_id) {
            if (StringUtil.isBlank(broker_id_bak)) {
                return VOUtil.genErrorResult(HSBCPSErrorCodes.NOT_LOGGED, HSBCPSBackNumVO.class);
            }
            broker_id = Long.valueOf(broker_id_bak);
        }
        //校验是否点过赞
        int count = this.upvoteWaterService.upvoteCount(customer.getCustomer_id(), broker_id, target_id,
                target_type);
        if (count > 0) {
            return VOUtil.genErrorResult(QuestionErr.HAS_UPVOTE, HSBCPSBackNumVO.class);
        }
        
        //观点说点赞
        if (target_type.equals(String.valueOf(UpvoteStatus.VIEWPOINT_UPVOTE.getVal()))) {
            ViewpointMsg msg = this.viewpointMsgService.get(target_id);
            if (null != msg) {
                if (!broker_id.equals(msg.getBroker_id())) {
                    return VOUtil.genErrorResult(SysMgtErr.NO_SUCH_VIEWPOINT_ID, HSBCPSBackNumVO.class);
                }
                if (null != msg.getViewpoint_status()
                        && ViewpointStatusType.SEND.getVal() != msg.getViewpoint_status().intValue()) {
                    return VOUtil.genErrorResult(SysMgtErr.NO_SEND_VIEWPOINT, HSBCPSBackNumVO.class);
                }
                msg.setUpvote_num(msg.getUpvote_num() + 1);
                this.viewpointMsgService.updateCAS(msg);
                vo.setNum(msg.getUpvote_num());
            } else {
                return VOUtil.genErrorResult(SysMgtErr.NO_SUCH_VIEWPOINT_ID, HSBCPSBackNumVO.class);
            }
        }
        //问与答点赞
        if (target_type.equals(String.valueOf(UpvoteStatus.QUESTION_UPVOTE.getVal()))) {
            Question ques = this.questionSerivce.get(target_id);
            if (null != ques) {
                if (!broker_id.equals(ques.getBroker_id())) {
                    return VOUtil.genErrorResult(SysMgtErr.NO_SUCH_QUESTION, HSBCPSBackNumVO.class);
                }
                if (null == ques.getAnswer_status()
                        || AnswerStatus.ANSWERD.getVal() != Integer.parseInt(ques.getAnswer_status())) {
                    return VOUtil.genErrorResult(QuestionErr.NO_ANSWER, HSBCPSBackNumVO.class);
                }
                ques.setUpvote_num(ques.getUpvote_num() + 1);
                this.questionSerivce.update(ques);
                vo.setNum(ques.getUpvote_num());
            } else {
                return VOUtil.genErrorResult(SysMgtErr.NO_SUCH_QUESTION, HSBCPSBackNumVO.class);
            }
        }
        //记录点赞流水
        this.upvoteWaterService.saveUpvoteWater(customer.getCustomer_id(), broker_id, target_id, target_type);
        //增加积分
        pointAddService.addPoint(customer.getMobile(), PointType.UPVOTE, customer.getUser_id(),
                customer.getTenant_id());
        return VOUtil.setSuccessResult(vo);
    }
    
    @Override
    public HSBCPSBackNumVO funcBrokerUpvoteClick(BrokerUpvoteClickForm param) {
        HSBCPSBackNumVO vo = new HSBCPSBackNumVO();
        BrokerVote brokerVote = brokerVoteService.getVoteByBrokerId(param.getBroker_id(), param.getVote_type());
        
        if (brokerVote == null) {
            return VOUtil.genErrorResult(HSBCPSErrorCodes.HSBCSErr.NO_CLIENTPROFILE, HSBCPSBackNumVO.class);
        }
        /*sql慢查询优化---去掉原来的sql函数使用*/
        int count = brokerVoteLogService.dayVoteFlag(param.getOpenid(), brokerVote.getTenant_id(),
                param.getVote_type(), getDay(new Date()));
        /*查询今日已投票次数*/
        if (count > 2) {
            return VOUtil.genErrorResult(SysMgtErr.CAN_NOT_VOTE_AGAIN, HSBCPSBackNumVO.class);
        }
        BrokerVoteLog brokerVoteLog = new BrokerVoteLog();
        brokerVoteLog.setBroker_id(param.getBroker_id());
        brokerVoteLog.setOpenid(param.getOpenid());
        brokerVoteLog.setVote_time(new Date());
        brokerVoteLog.setTenant_id(brokerVote.getTenant_id());
        brokerVoteLog.setVote_type(param.getVote_type());
        brokerVoteLogService.save(brokerVoteLog);
        brokerVoteService.addVoteNum(param.getBroker_id(), brokerVote.getTenant_id(), param.getVote_type(),
                getLastManageVoteDate(brokerVote.getTenant_id(), param.getVote_type()));
        vo.setNum(++count);
        return VOUtil.setSuccessResult(vo);
    }
    
    @Override
    public VoteRecordListBack funcGetVoteRecordList(RecordListForm param) {
        String broker_name = param.getBroker_name();
        String order_type = param.getOrder_type();
        String position_str = param.getPosition_str();
        String openId = param.getOpenid();
        String vote_type = getString(param.getVote_type(), VoteType.BASE.getVal());
        Integer tenantId = ValueUtil.getInt(param.getTenant_id());
        Date today = getDay(new Date());
        if (tenantId == 0 && !StringUtil.isBlank(param.getTenant_key())) {
            Tenant tenant = tenantService.getByKey(param.getTenant_key());
            if (tenant != null) {
                tenantId = tenant.getTenant_id();
            }
        }
        List<BrokerVoteLog> brokerVoteLogs = null;
        boolean needStatus = StringUtil.isEmpty(openId);// 1 未投 0已投
        boolean hasVote = true;
        Integer request_num = ValueUtil.getInt(param.getRequest_num(), ConfigValues.getRequestNum());
        Integer position = StringUtil.isBlank(position_str) ? 0 : Integer.parseInt(position_str);
        /*设置最近导表时间*/
        List<VoteRecordListView> listViews = null;
        switch (order_type) {
            case "3":
                BrokerFinanceQueryCondition condition = new BrokerFinanceQueryCondition();
                condition.setBroker_name(broker_name);
                condition.setFinance_time(getLastManageZXConfigDate(tenantId));
                condition.setVote_time(getLastManageVoteDate(tenantId, vote_type));
                condition.setPosition(position);
                condition.setRequest_num(request_num);
                condition.setTenant_id(tenantId);
                condition.setVote_type(vote_type);
                listViews = zxBrokerFinanceService.getFinanceOrderList(condition);
                break;
            case "2":
            case "1":
            case "0":
            default:
                BrokerVoteQueryCondition condition1 = new BrokerVoteQueryCondition();
                condition1.setTenant_id(tenantId);
                condition1.setBroker_name(broker_name);
                condition1.setOrder_type(order_type);
                condition1.setPosition(position);
                condition1.setRequest_num(request_num);
                condition1.setCreate_time(getLastManageVoteDate(tenantId, vote_type));
                condition1.setVote_type(vote_type);
                listViews = brokerVoteService.getVoteRecordList(condition1);
                break;
        }
        
        if (!needStatus) {
            brokerVoteLogs = brokerVoteLogService.findBrokerVoteToday(openId, tenantId, today, vote_type);
        }
        if (brokerVoteLogs == null || brokerVoteLogs.size() == 0) {
            hasVote = false;//未曾投票
        }
        ArrayList<VoteRecordListData> listDatas = new ArrayList<>();
        VoteRecordListBack result = new VoteRecordListBack();
        int i = 1;
        List<BrokerFinance> brokerFinances = getZxBrokerFinances(tenantId);
        for (VoteRecordListView listView : listViews) {
            VoteRecordListData voteRecordListData = new VoteRecordListData();
            voteRecordListData.setBroker_id(listView.getBroker_id());
            voteRecordListData.setBroker_name(listView.getBroker_name());
            voteRecordListData.setInvest_style(listView.getInvest_style());
            voteRecordListData.setCumulative_record(listView.getCumulative_record());
            voteRecordListData.setRotation_rate(listView.getRotation_rate());
            voteRecordListData.setVote_num(listView.getVote_num());
            /*非常规投票，增加辅助信息*/
            if (!vote_type.equals(VoteType.BASE.getVal())) {
                /*设置配置率*/
                if (order_type.equals("3")) {
                    voteRecordListData.setConfig_record(listView.getConfig_record());
                } else {
                    if (brokerFinances != null && brokerFinances.size() > 0) {
                        setFinanceConfig(voteRecordListData, tenantId);
                    }
                }
            }
            
            if (hasVote) {
                for (BrokerVoteLog brokerVoteLog : brokerVoteLogs) {
                    if (brokerVoteLog.getBroker_id().equals(listView.getBroker_id())) {
                        voteRecordListData.setVote_status("0");
                        break;
                    } else {
                        voteRecordListData.setVote_status("1");
                    }
                }
            } else {
                voteRecordListData.setVote_status("1");
            }
            
            voteRecordListData.setPosition_str(String.valueOf(position + i));
            voteRecordListData.setRanking(listView.getRanking());
            String broker_avator = listView.getBroker_avatar() == null ? "" : listView.getBroker_avatar();
            voteRecordListData.setBroker_avatar(ConfigValues.getInterfaceOssAddr() + broker_avator
                    + "/92f17e36e6cf0a8083ff435fc708a372");
            listDatas.add(voteRecordListData);
            i++;
        }
        if (!StringUtil.isEmpty(broker_name) && listDatas.size() == 1) {
            /*相当于获取投顾详情*/
            VoteRecordListData data = listDatas.get(0);
            /*返回增加user_id*/
            data.setUser_id(getUserIdFromBrokerManager(data.getBroker_id(), tenantId));
            
        }
        result.setData_list(listDatas);
        return VOUtil.setSuccessResult(result);
    }
    
    @Override
    public BatchImportVoteBackForm funcBatchImportVote(BatchImportVoteListForm param) {
        /*导入投票处理*/
        return importVoteAndRotate(param.getDataList());
    }
    
    @Override
    public BatchImportVoteBackForm funcBatchImportFinanceConfig(BatchImportZXConfigListForm param) {
        return importZXConfig(param.getDataList());
    }
    
    private BatchImportVoteBackForm importVoteAndRotate(List<BatchImportVoteForm> dataList) {
        int i = 0;
        Integer tenantId = null;
        String voteType = null;
        
        for (BatchImportVoteForm batchImportVoteForm : dataList) {
            Broker broker = checkMobile(batchImportVoteForm.getMobile());
            if (broker == null) {
                continue;
            }
            Date now = new Date();
            
            BrokerVote brokerVote = new BrokerVote();
            brokerVote.setBroker_id(broker.getBroker_id());
            brokerVote.setTenant_id(broker.getTenant_id());
            tenantId = broker.getTenant_id();
            brokerVote.setBroker_avatar(broker.getBroker_avatar());
            voteType = getString(batchImportVoteForm.getVote_type(), VoteType.BASE.getVal());
            brokerVote.setBroker_name(batchImportVoteForm.getBroker_name());
            brokerVote.setCumulative_record(new BigDecimal(batchImportVoteForm.getCumulative_record().trim()));
            brokerVote.setInvest_style(batchImportVoteForm.getInvest_style());
            brokerVote.setRotation_rate(new BigDecimal(batchImportVoteForm.getRotation_rate().trim()));
            brokerVote.setVote_type(voteType);//目前默认为1
            brokerVote.setPosition_str(PositionStrUtil.getPositionStr());
            brokerVote.setCreate_time(now);
            brokerVote.setUpdate_time(now);
            BrokerVote brokerVoteOld = brokerVoteService.findByBorkerId(broker.getTenant_id(),
                    broker.getBroker_id(), voteType);
            if (brokerVoteOld == null) {
                brokerVote.setVote_num(0);
                brokerVoteService.save(brokerVote);
            } else {
                brokerVote.setVote_num(brokerVoteOld.getVote_num());
                if (DateUtil.yyyyMMdd.format(now).equals(DateUtil.yyyyMMdd.format(brokerVoteOld.getCreate_time()))) {
                    /*每天只保留一份数据*/
                    brokerVote.setBroker_vote_id(brokerVoteOld.getBroker_vote_id());
                    brokerVoteService.update(brokerVote);
                } else {
                    brokerVoteService.save(brokerVote);
                }
            }
            
            i++;
        }
        BatchImportVoteBackForm batchImportVoteBackForm = new BatchImportVoteBackForm();
        batchImportVoteBackForm.setNum(i);
        batchImportVoteBackForm.setTenant_id(tenantId);
        //lastManageVoteDate = getDay(new Date());
        if (i > 0) {
            setDateToCache(CacheKeys.LAST_MANAGE_VOTE_IMPORT_DATE_PREFIX, tenantId + "_" + voteType,
                    getDay(new Date()));
        }
        
        return VOUtil.setSuccessResult(batchImportVoteBackForm);
    }
    
    private BatchImportVoteBackForm importZXConfig(List<BatchImportZXConfigForm> dataList) {
        int i = 0;
        Integer tenantId = null;
        Date today = getDay(new Date());
        for (BatchImportZXConfigForm batchImportZXConfigForm : dataList) {
            Broker broker = checkMobile(batchImportZXConfigForm.getMobile());
            if (broker == null) {
                continue;
            }
            tenantId = broker.getTenant_id();
            BrokerFinance brokerFinance = new BrokerFinance();
            brokerFinance.setBroker_id(broker.getBroker_id());
            brokerFinance.setTenant_id(tenantId);
            brokerFinance.setBroker_name(batchImportZXConfigForm.getBroker_name());
            brokerFinance.setCreate_time(new Date());
            brokerFinance.setPosition_str(PositionStrUtil.getPositionStr());
            brokerFinance.setConfig_record(new BigDecimal(batchImportZXConfigForm.getConfigure_record().trim()));
            brokerFinance.setUpdate_time(new Date());
            BrokerFinance brokerFinanceOld = zxBrokerFinanceService.findTodayImport(tenantId,
                    broker.getBroker_id(), today);
            if (brokerFinanceOld == null) {
                zxBrokerFinanceService.save(brokerFinance);
            } else {
                brokerFinance.setBroker_finance_id(brokerFinanceOld.getBroker_finance_id());
                zxBrokerFinanceService.update(brokerFinance);
            }
            
            i++;
        }
        BatchImportVoteBackForm batchImportVoteBackForm = new BatchImportVoteBackForm();
        batchImportVoteBackForm.setNum(i);
        if (i > 0) {
            batchImportVoteBackForm.setTenant_id(tenantId);
            /*导入成功，则更新*/
            lastManageZXConfigDate = today;
            setDateToCache(CacheKeys.LAST_MANAGE_FINANCE_IMPORT_DATE_PREFIX, tenantId.toString(), today);
            brokerFinancesMap.put(tenantId, null);
        }
        
        return VOUtil.setSuccessResult(batchImportVoteBackForm);
    }
    
    private Broker checkMobile(String mobile) {
        if (StringUtil.isBlank(mobile)) {
            return null;
        } else {
            mobile = mobile.trim();
            BigDecimal bd = new BigDecimal(mobile);
            mobile = bd.toPlainString();
        }
        
        Broker broker = brokerService.getByMobile(mobile);
        if (broker == null) {
            /*未注册*/
            return null;
        }
        return broker;
    }
    
    private Date getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date == null) {
            return null;
        }
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        return calendar.getTime();
    }
    
    /*获取最新一次brokervote--date*/
    private Date getLastManageVoteDate(Integer tenantId, String voteType) {
        String field = tenantId + "_" + voteType;
        Date lastDate = getDateFromCache(CacheKeys.LAST_MANAGE_VOTE_IMPORT_DATE_PREFIX, field);
        if (lastDate == null) {
            lastDate = getDay(brokerVoteService.getLastVoteDate(tenantId, voteType));
            setDateToCache(CacheKeys.LAST_MANAGE_VOTE_IMPORT_DATE_PREFIX, field, lastDate);
        }
        
        return lastDate;
    }
    
    private Date getLastManageZXConfigDate(Integer tenantId) {
        if (tenantId == null) {
            return null;
        }
        Date lastDate = getDateFromCache(CacheKeys.LAST_MANAGE_FINANCE_IMPORT_DATE_PREFIX, tenantId.toString());
        if (lastDate == null) {
            lastDate = getDay(zxBrokerFinanceService.getLastImportTime(tenantId));
            setDateToCache(CacheKeys.LAST_MANAGE_FINANCE_IMPORT_DATE_PREFIX, tenantId.toString(), lastDate);
        }
        if (lastManageZXConfigDate == null || (lastDate != null && lastManageZXConfigDate.before(lastDate))) {
            brokerFinancesMap.put(tenantId, null);
            lastManageZXConfigDate = lastDate;
        }
        return lastDate;
    }
    
    private Date getDateFromCache(String key, String field) {
        if (StringUtil.isEmpty(field)) {
            return null;
        }
        CacheHelper cacheHelper = CacheHelper.getInstance();
        String lastTime = cacheHelper.hget(key, field);
        try {
            return StringUtil.isEmpty(lastTime) ? null : DateUtil.yyyyMMdd.parse(lastTime);
        } catch (Exception e) {
            logger.error("解析时间字符串错误{}", lastTime);
            return null;
        }
    }
    
    private void setDateToCache(String key, String field, Date date) {
        if (StringUtil.isEmpty(field) || date == null) {
            return;
        }
        CacheHelper cacheHelper = CacheHelper.getInstance();
        cacheHelper.hset(key, field, DateUtil.yyyyMMdd.format(date));
    }
    
    private List<BrokerFinance> getZxBrokerFinances(Integer tenantId) {
        List<BrokerFinance> brokerFinanceList = brokerFinancesMap.get(tenantId);
        if (brokerFinanceList == null) {
            synchronized (this) {
                brokerFinanceList = zxBrokerFinanceService.findFinanceList(tenantId,
                        getLastManageZXConfigDate(tenantId));
                brokerFinancesMap.put(tenantId, brokerFinanceList);
            }
        }
        return brokerFinanceList;
    }
    
    private void setFinanceConfig(VoteRecordListData voteRecordListData, Integer tenantId) {
        List<BrokerFinance> brokerFinanceList = brokerFinancesMap.get(tenantId);
        if (brokerFinanceList == null || brokerFinanceList.size() == 0) {
            return;
        }
        for (BrokerFinance brokerFinance : brokerFinanceList) {
            if (brokerFinance.getBroker_id().equals(voteRecordListData.getBroker_id())) {
                voteRecordListData.setConfig_record(brokerFinance.getConfig_record().toPlainString());
                break;
            }
        }
    }
    
    private String getString(Object object, String defaultValue) {
        if (object == null) {
            return defaultValue;
        }
        String temp = String.valueOf(object);
        return StringUtil.isEmpty(temp) ? defaultValue : temp;
    }
    
    private Long getUserIdFromBrokerManager(Long brokerId, Integer tenantId) {
        BrokerManager brokerManager = brokerManagerService.getBrokerManager(brokerId, tenantId);
        return brokerManager == null ? null : brokerManager.getUser_id();
    }
}
